package awesomeDocumentIO;

import java.awt.Color;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;


import misc.Vals;
import document.AwesomeDocument;

/**
 * Used to export document type information to the files system.
 * @author Brittin
 *
 */
public class AwesomeDocumentExporter {
	
	/**
	 * Returns true if the passed document was successfully written to file.
	 * @param doc document to export.
	 * @return true if the passed document was successfully written to file.
	 */
	public static boolean exportDocumentType(AwesomeDocument doc) {
		
//		String docfilepath = Vals.docDirectoryPath + File.separator + doc.getLabel() + Vals.docFileExt;
		String dictfilepath = Vals.docDirectoryPath + File.separator + doc.getLabel() + Vals.docDictExt;
		
		if (!updateDirectory(doc.getLabel(), doc.getExtension()))
			return false;
//		if (!writeDocFile(doc, docfilepath))
//			return false;
		if (!writeDictFile(doc.getLibrary(), dictfilepath))
			return false;
		
		return true;
	}
	
	/**
	 * Returns true if the document type directory is successfully updated.
	 * @param label label of the document type
	 * @param ext extension of the document type
	 * @return true if the document type directory is successfully updated.
	 */
	private static boolean updateDirectory(String label, String ext) {
		List<String> labels = new ArrayList<String>();
		List<String> extensions = new ArrayList<String>();
		
		try {
			// Open the directory and get all the labels
			BufferedReader reader = new BufferedReader(new FileReader(Vals.docDirectoryFile));
			
			String line = null;
			
			while ( !((line = reader.readLine()) == null )) {
				labels.add(line);
				line = reader.readLine();
				extensions.add(line);
			}
			
			reader.close();
			
			if(labels.contains(label))
				return true;
			// print the old information
			FileWriter outFile = new FileWriter(Vals.docDirectoryFile);
			PrintWriter out = new PrintWriter(outFile);
			Iterator<String> iter = extensions.iterator();
			for(String str : labels) {
				out.println(str);
				out.println(iter.next());
			}
			
			// add the new info
			out.println(label);
			out.println(ext);
			out.close();
			return true;
		} catch (IOException ex) {
			System.err.println(ex);
			return false;
		}
	}
	
	/**
	 * Returns true if the passed doc is successfully written to file.
	 * @param doc the document to use.
	 * @param filepath the path of the file to use.
	 * @return true if the passed doc is successfully written to file.
	 */
	private static boolean writeDocFile(AwesomeDocument doc, String filepath) {
		try {
			FileWriter outFile = new FileWriter(filepath);
			PrintWriter out = new PrintWriter(outFile);
			out.println(Vals.docFileHeader);
			
			out.println(Vals.docLabelTab + " " + doc.getLabel());
			out.println(Vals.docExtTab + " " + doc.getExtension());
			
			out.println(Vals.docFileFooter);
			out.close();
			return true;
		} catch (IOException ex) {
			System.err.println(ex);
			return false;
		}
	}
	
	/**
	 * Returns true if the dictionary was successfully written to file.
	 * @param dict dictionary to write to file.
	 * @param filepath the path of the file to write to.
	 * @return true if the dictionary was successfully written to file.
	 */
	private static boolean writeDictFile(HashMap<String, Color> dict, String filepath) {
		if (dict == null)
			return false;
		try {
			FileWriter outFile = new FileWriter(filepath);
			PrintWriter out = new PrintWriter(outFile);
			out.println(Vals.docFileHeader);
			
			for(String key : dict.keySet()) {
				out.println(Vals.docLibraryKeyTab + " " + key);
				out.println(Vals.docLibraryColorTab + " " + formatColorString(dict.get(key)));
			}
			out.println(Vals.docFileFooter);
			out.close();
			return true;
		} catch (IOException ex) {
			System.err.println(ex);
			return false;
		}
	}
	
	/**
	 * Returns the formatted color.toString() string to be used in file i/o.
	 * @param color the color to use.
	 * @return the formatted color.toString() string to be used in file i/o.
	 */
	private static String formatColorString(Color color) {
		if (color == null)
			return null;
		
		// Color.toString() is formatted in the following way:
		// java.awt.Color[r=255,g=175,b=175]
		// Decompose this string to just the r, g, b values
		String retVal = color.toString();
		
		retVal = retVal.substring(retVal.indexOf('[') + 1);
		retVal = retVal.substring(0, retVal.lastIndexOf(']'));
		return retVal;
	}
	
//	private static HashMap<Color, String> getColorStringMap() {
//		HashMap<Color, String> map = new HashMap<Color, String>();
//		map.put(Color.black, "black");
//		map.put(Color.BLACK, "black");
//		map.put(Color.blue, "blue");
//		map.put(Color.BLUE, "blue");
//		map.put(Color.cyan, "cyan");
//		map.put(Color.CYAN, "cyan");
//		map.put(Color.DARK_GRAY, "darkGray");
//		map.put(Color.darkGray, "darkGray");
//		map.put(Color.gray, "gray");
//		map.put(Color.GRAY, "gray");
//		map.put(Color.green, "green");
//		map.put(Color.GREEN, "green");
//		map.put(Color.LIGHT_GRAY, "lightGray");
//		map.put(Color.lightGray, "lightGray");
//		map.put(Color.magenta, "magenta");
//		map.put(Color.MAGENTA, "magenta");
//		map.put(Color.orange, "orange");
//		map.put(Color.ORANGE, "orange");
//		map.put(Color.pink, "pink");
//		map.put(Color.PINK, "pink");
//		map.put(Color.red, "red");
//		map.put(Color.RED, "red");
//		map.put(Color.white, "white");
//		map.put(Color.WHITE, "white");
//		map.put(Color.yellow, "yellow");
//		map.put(Color.YELLOW, "yellow");
//		return map;
//	}

	
	/**
	 * Returns the colors available for use in document types.
	 */
	private static HashMap<String, Color> getColorStringMap() {
		HashMap<String, Color> map = new HashMap<String, Color>();
		map.put("black", Color.black);
		map.put( "blue", Color.blue);
		map.put("cyan", Color.cyan);
		map.put("dark_gray", Color.darkGray );
		map.put("gray", Color.gray );
		map.put("green", Color.green );
		map.put("light_gray", Color.lightGray );
		map.put("magenta", Color.magenta );
		map.put("orange", Color.orange );
		map.put("pink", Color.pink );
		map.put("red", Color.red );
		map.put("white",Color.white );
		map.put("yellow", Color.yellow );
		return map;
	}
	
	/**
	 * Returns true if the new syntax keyword was successfully exported.
	 * @param label label of the document type associated with the new syntax.
	 * @param keyword syntax keyword
	 * @param colorString keyword color
	 * @return true if the new syntax keyword was successfully exported.
	 */
	public static boolean exportNewSyntax(String label, String keyword,
			String colorString) {
		HashMap<String, Color> colormap = getColorStringMap();
		
		// Get the old dict
		String dictfilepath = Vals.docDirectoryPath + File.separator + label + Vals.docDictExt;
		HashMap<String, Color> dict = AwesomeDocumentImporter.readDictFromFile(dictfilepath);
		if (dict == null)
			return false;
		Color color = colormap.get(colorString);
		dict.put(keyword, color);
		
		// Write to old dict

		return writeDictFile(dict, dictfilepath);
	}
}
